use axum::{extract::{Request, FromRequestParts, State}, middleware::Next, response::Response};
use axum_extra::{TypedHeader, headers::{Authorization, authorization::Bearer}};
use tracing::{info, warn};
use axum::http::StatusCode;
use axum::response::IntoResponse;
use crate::{AppError, AppState, User};

pub async fn verify_token(State(state): State<AppState>,
                          request: Request, next: Next) -> Response {
    let (mut parts, body) = request.into_parts();

    let map_values = &parts.headers;
    for m in map_values {
        info!("head :k {:?}, v {:?}", m.0, m.1);
    }

    match TypedHeader::<Authorization<Bearer>>::from_request_parts(&mut parts, &state).await {
        Ok(TypedHeader(Authorization(bearer))) => {
            // todo!()
            let token = bearer.token();

            match state.dk.verify(token) {
                Ok(user) => {
                    let mut req = Request::from_parts(parts, body);
                    req.extensions_mut().insert(user);
                    next.run(req).await
                }
                Err(e) => {
                    let msg = format!("verity token failed: {}", e);
                    warn!(msg);
                    (StatusCode::UNAUTHORIZED, msg).into_response()
                }
            }
        }
        Err(e) => {
            let msg = format!("parse Authorization header failed: {}", e);
            warn!(msg);

            (StatusCode::UNAUTHORIZED, msg).into_response()
        }
    }
}